#include "stdafx.h"


CBoard::CBoard()
{
    Rst();
}


CBoard::~CBoard()
{

}

uint CBoard::Print()
{
    uint pie = 0;
    BITBOARD code = 0;
    cout << endl; 
    cout << "Castles:"<< flags << ", Ep:"<< enpassant << endl; 
    for (uint ln = 0; ln < 8; ln++)
       {
            cout << " ";        
            for( uint col = 0; col < 8; col++ )
            {
                if ( IS_WHITE( pie = board[MAILBOX64[COORD2SQUARE(ln, col)]] ) )
                    {
                        cout << CHAR_WPIE[pie & 0x7];
                        code+=pie*(ln*8+col);
                    }
                else if ( IS_BLACK( pie = board[MAILBOX64[COORD2SQUARE(ln, col)]] ) )
                    {
                        cout << CHAR_BPIE[pie & 0x7];
                        code+=pie*(ln*8+col);
                    }
                else 
                    cout << '.';
            }
            cout << endl;
       }
    cout << " abcdefgh" << endl;
    code += (white_pieces + black_pieces + flags + enpassant);
    cout << " Code: " << (BITBOARD)code <<endl;
    cout << " Hash: " << hex << (uint64)GetHash() << dec << endl;
    return 0;
}

uint CBoard::Rst()
{
    for (uint i = 0; i < 128; i++) board[i] = NN;
    for (uint i = 0; i < 64; i++)  board[MAILBOX64[i]] = 0;
    white_pieces = 0;
    black_pieces = 0;
    history.Reset();
    wking       = 0;
    bking       = 0;
    hash->Reset();
    return 0;
} 
 
uint CBoard :: Add( uint sq, uint piece )
{
    board[ sq ] = piece;
    hash->AddPiece( sq, piece );
    if ( piece == WK ) wking = sq;
    if ( piece == BK ) bking = sq;
    if (IS_WHITE(piece)) white_pieces |= BIT(MAILBOX[sq]);   
    if (IS_BLACK(piece)) black_pieces |= BIT(MAILBOX[sq]); 
    // correct castles flag
    SetFlags( GetFlags() & (~( CASRLE_MARK[sq] )) );
    return 0;
}

uint CBoard :: Remove( uint sq )
{
    
    if (IS_WHITE(board[ sq ])) white_pieces &= ~BIT(MAILBOX[sq]);   
    if (IS_BLACK(board[ sq ])) black_pieces &= ~BIT(MAILBOX[sq]); 
    if ( board[sq] ) hash->RemovePiece( sq, board[sq]);
    board[ sq ] = 0;
    // correct castles flag
    SetFlags( GetFlags() & (~( CASRLE_MARK[sq] )) );
    return 0;
}

uint CBoard :: Select( uint color )
{
    pieces = ( IS_WHITE( color ) ) ? white_pieces : black_pieces;
    return 0;
}

uint CBoard :: Next( )
{
    if ( !pieces ) return 0; // done
    BITBOARD new_pieces = ERASE_FIRST_SET_BIT( pieces );
    BITBOARD pie        = new_pieces ^ pieces;
    pieces = new_pieces;
    return ( MAILBOX64[util.PopCnt( pie-1 )] );
}

uint CBoard :: PushInfo()
{
    history.Push( BYTES2UINT( 0,color,flags,enpassant ) );
    hash->Push();
    return 0;
};
uint CBoard :: PopInfo()
{
    uint data = history.Pop();
    color       = BYTE_FROM_UINT( data, 2 );
    flags       = BYTE_FROM_UINT( data, 1 );
    enpassant   = BYTE_FROM_UINT( data, 0 );
    hash->Pop();
    return 0;
};

uint CBoard :: UnderAtack( uint sq, uint color )
{
    // pawns
    int  step       = IS_WHITE( color ) ? (10) : (-10);
    uint pie        = color|PAWN;
    if ( ( board[sq+step-1] == pie ) || (board[sq+step+1] == pie  ) )
        return 1;


    // sliders
    uint opponent = OPPONENT(color);
    uint to, b;
    uint from = sq;
    uint p   = ROOK;
    for (uint dir = DIRFROM[p]; dir < DIRTO[p]; dir++ )
    {
        to = from;
        for ( uint step = 0; step < DIRLEN[p]; step++ )
        {
            to += SLIDE_MOVE[dir];
            b = board[to];
            if ( b )
            {
                if (( b == (color|ROOK)  ) || 
                    ( b == (color|QUEEN) ) ||
                    ( ( b == (color|KING) ) && ( step==0 ) ))
                        return 2;
                else break;
            }
        }
    }
    p   = BISHOP;
    for (uint dir = DIRFROM[p]; dir < DIRTO[p]; dir++ )
    {
        to = from;
        for ( uint step = 0; step < DIRLEN[p]; step++ )
        {
            to += SLIDE_MOVE[dir];
            b = board[to];
            if ( b )
            {
                if (( b == (color|BISHOP)  ) || 
                    ( b == (color|QUEEN) ) ||
                    ( ( b == (color|KING) ) && ( step==0 ) ))
                        return 3;
                else break;
            }
        }
    }
    p   = KNIGHT;
    for (uint dir = DIRFROM[p]; dir < DIRTO[p]; dir++ )
    {
        to = from;
        for ( uint step = 0; step < DIRLEN[p]; step++ )
        {
            to += SLIDE_MOVE[dir];
            b = board[to];
            if ( b )
            {
                if ( b == (color|KNIGHT)  )
                    return 4;
                else break;
            }
        }
    }
    return 0;
};

uint CBoard :: UnderCheck( uint c )
{
    return UnderAtack( GetKingSquare(c), OPPONENT(c) );
}

uint CBoard::PrintChecks(uint color)
{
    uint pie = 0;
    BITBOARD code = 0;
    for (uint ln = 0; ln < 8; ln++)
       {
            cout << " ";        
            for( uint col = 0; col < 8; col++ )
            {
                uint ua = UnderAtack(MAILBOX64[COORD2SQUARE(ln, col)],color);
                if ( ua ) cout << ua;
                else cout << ".";
            }
            cout << endl;
       }
    cout << " abcdefgh" << endl;
    return 0;
}

uint64 CBoard :: GetHash( )
{
    uint ep = 0;
    if (enpassant)
        {
            if ( (PAWN_ENPASSANT[enpassant] == CB) && ( (board[enpassant-11] == BP) || (board[enpassant-9] == BP) ) )
                ep = enpassant;
            else if ( (PAWN_ENPASSANT[enpassant] == CW) && ( (board[enpassant+11] == WP) || (board[enpassant+9] == WP) ) )
                ep = enpassant;
            else 
                ep = 0;
        }
    return hash->Get( color, ep, flags );
}

uint64 CBoard :: IsDraw( )
{
    return hash->IsRepetition( );
}